package com.android.jacvdemo;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.TextureView;
import android.widget.ImageView;


import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 推流
 */
public class MainActivity extends AppCompatActivity implements Runnable {

    private TextureView textureView;
    private Camera mCamera;

    private Handler handler;

    private ImageView iv;

    private Frame yuvImage;

    private FFmpegFrameRecorder recorder;

    private File ffmpeg_link = new File(Environment.getExternalStorageDirectory(), "/1/stream.mp4");

    private long startTime;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textureView = findViewById(R.id.textureView);
        iv = findViewById(R.id.iv);
        mCamera = Camera.open();

        yuvImage = new Frame(320, 240, Frame.DEPTH_UBYTE, 2);

        recorder = new FFmpegFrameRecorder("rtmp://push.eevvev.cn/live/67735b90b4568125ed6c3f678819b6e058", 320, 240,1);
        recorder.setFormat("flv");
//        recorder.setSampleRate(sampleAudioRateInHz);
        // Set in the surface changed method
        recorder.setFrameRate(20);

        textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int o, int i1) {
                try {
                    mCamera.setPreviewTexture(surfaceTexture);
                    mCamera.setDisplayOrientation(90);
                    Camera.Parameters parameters=mCamera.getParameters();
                    parameters.set("orientation", "portrait");
//                    parameters.setPreviewFormat(ImageFormat.NV21);
//                    parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);


                    List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
                    // Sort the list in ascending order
                    Collections.sort(sizes, new Comparator<Camera.Size>() {

                        public int compare(final Camera.Size a, final Camera.Size b) {
                            return a.width * a.height - b.width * b.height;
                        }
                    });

                    // Pick the first preview size that is equal or bigger, or pick the last (biggest) option if we cannot
                    // reach the initial settings of imageWidth/imageHeight.
                    for(int i = 0; i < sizes.size(); i++) {
//                        if((sizes.get(i).width >= imageWidth && sizes.get(i).height >= imageHeight) || i == sizes.size() - 1) {
//                            imageWidth = sizes.get(i).width;
//                            imageHeight = sizes.get(i).height;
//                            Log.v(LOG_TAG, "Changed to supported resolution: " + imageWidth + "x" + imageHeight);
//                            break;
//                        }
                        Log.e("HHH", "onSurfaceTextureAvailable: " + sizes.get(i).width + "===" + sizes.get(i).height );
                    }
                    parameters.setPreviewSize(320, 240);

                    parameters.setPreviewFrameRate(20);
                    mCamera.setParameters(parameters);
                    mCamera.startPreview();

                    recorder.start();
                    startTime = System.currentTimeMillis();

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {

            }

            @Override
            public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
                return false;
            }

            @Override
            public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {

            }
        });

        mCamera.setPreviewCallback(new Camera.PreviewCallback() {
            @Override
            public void onPreviewFrame(byte[] bytes, Camera camera) {
                if (handler!=null) {
                    Message obtain = Message.obtain();
                    obtain.obj = bytes;
                    obtain.what = 1;
                    handler.sendMessage(obtain);
                    Log.e("HHH", "onPreviewFrame: " + bytes.length );
                }
            }
        });
        // 创建线程
        new Thread(MainActivity.this).start();
        Log.e("HHH", "onCreate: " + "证明开了日志" );
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        try {
            if (recorder!=null) {
                recorder.stop();
                recorder.release();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (mCamera != null){
            mCamera.setPreviewCallback(null);
            mCamera.release();        // release the camera for other applications
            mCamera = null;
        }
    }

    @Override
    public void run() {
        // 创建handler
        Looper.prepare();
        handler = new MyHandler();
        Looper.loop();
    }

    class MyHandler extends Handler {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);

            if (msg.what == 1) {
                final byte[] bytes = (byte[]) msg.obj;
                ByteBuffer position = (ByteBuffer) yuvImage.image[0].position(0);
                Log.e("HHH", "handleMessage: " + position.array().length );  // 3110400
                position.put(bytes);

                try {
                    Log.e("HHH", "Writing Frame");
                    long t = 1000 * (System.currentTimeMillis() - startTime);
                    if(t > recorder.getTimestamp()) {
                        recorder.setTimestamp(t);
                    }
                    recorder.record(yuvImage);
                } catch(Exception e) {
                    Log.e("HHH","handleMessage: ", e);
                    e.printStackTrace();
                }

                Log.e("HHH", "handleMessage: " + "写入成功" );
            }
        }
    }
}
